package game;

import java.awt.Cursor;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.MemoryImageSource;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.Timer;

public class BeautyContest extends Game{
   int participants=10;
   double factor=0.5;
   double win_amount = 2.0 ;
   int limit=100,choice;
   int totalTime=60,secs = totalTime, timeTaken=0;
   Timer time = new Timer(1000, new TimeListener());
   String state="init";

   /** Amount we increment the number by when choosing a number. */
   final int INCREMENT = 1;

   /** List of values that user can choose to send. Used in chooser JList. */
	LinkedList<Integer> moneyValues = new LinkedList<Integer>();

	/** Number of values to display in the chooser JList. */
	final int LIST_SIZE = 5;

	/** Half of list size. */
	int halfList;

	/** Maximum number of values the user could possibly choose given the
	 increment, and starting and stopping values. */
	int maxValues;

	/** List index we've displayed for the chooser list. */
	int listIndex = 0;

	// Game log constants.
	final int GL_WIN_LOSS = 0;
	final int GL_WIN_WIN = 1;

   /** Creates new form BeautyContest */
    public BeautyContest()
    {
        super();
//        super("",
//              false, //resizable
//              false, //closable
//              false, //maximizable
//              false);//iconifiable
//        javax.swing.plaf.InternalFrameUI ui = this.getUI();
//        ((javax.swing.plaf.basic.BasicInternalFrameUI)ui).setNorthPane(null);

        initComponents();
//        this.populateList();
        runner.addMouseListener(new BeautyContest.CheckMouse());
        this.addMouseListener(new BeautyContest.CheckMouse());
        time.start();
        int min = secs/60;
        int sec = secs%60;
        lblTime.setText(min+":"+((sec<10)?"0":"")+sec);
        hideMouse();
    }

    /** Creates new form BeautyContest and sets the parameters*/
    public BeautyContest(String params, int currentRep)
    {
        super();
//        super("",
//              false, //resizable
//              false, //closable
//              false, //maximizable
//              false);//iconifiable
//        javax.swing.plaf.InternalFrameUI ui = this.getUI();
//        ((javax.swing.plaf.basic.BasicInternalFrameUI)ui).setNorthPane(null);

        initComponents();
        this.setVisible(true);

		String paramPart[] = params.split(",");
        win_amount = Double.parseDouble (paramPart[2]);
		factor = Double.parseDouble(paramPart[3]);
        limit = Integer.parseInt(paramPart[4]);
        participants = Integer.parseInt(paramPart[5]);
		this.params = params;
		repTot = Integer.parseInt (paramPart[1]);
		repNum = currentRep;
		
//        this.populateList();

        runner.addMouseListener(new BeautyContest.CheckMouse());
		this.getGlassPane().addMouseListener(new BeautyContest.CheckMouse());
		valueList.addMouseListener (new BeautyContest.CheckMouse());
		hideMouse();

        time.start();
        int min = secs/60;
        int sec = secs%60;
        lblTime.setText(min+":"+((sec<10)?"0":"")+sec);

		// Assuming no loss of precision.
		maxValues = limit;
		halfList = (int) Math.floor (LIST_SIZE / 2);
		int numValues = maxValues - halfList + LIST_SIZE;
		for (listIndex = maxValues-halfList;
			listIndex < numValues; listIndex++) {
			moneyValues.add (INCREMENT * (listIndex % maxValues) + 1);
		}
		listIndex--;
		valueList.setListData(moneyValues.toArray(new Integer [LIST_SIZE]));
		valueList.setSelectedIndex(halfList);
    }

    private void hideMouse() {
        int[] pixels = new int[16 * 16];
        Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
        Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "invisibleCursor");
        this.getGlassPane().setCursor(transparentCursor);
		this.getGlassPane().setVisible(true);
        runner.setCursor(transparentCursor);
    }

	/**
     * Shift the value list to increase by one place.
     */
	private void incrementValueList() {
		listIndex++;
		moneyValues.remove();
		moneyValues.add (INCREMENT * (listIndex % maxValues) + 1);
		valueList.setListData (moneyValues.toArray(new Integer [LIST_SIZE]));
		valueList.setSelectedIndex (halfList);
	}

	class CheckMouse implements MouseListener{
        public void mousePressed(MouseEvent e) { hideMouse(); }
        public void mouseReleased(MouseEvent e) {}
        public void mouseEntered(MouseEvent e) {}
        public void mouseExited(MouseEvent e) {}
        public void mouseClicked(MouseEvent e) {
			int modifiers = e.getModifiers();
			
            if ((modifiers & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
                if(state.equals("end")) {
                      //do nothing
//                    setVisible(false);
//                    g.free = true;
                }
                else {
                    int num = Integer.parseInt(valueList.getSelectedValue()
						.toString());
					incrementValueList();
                }
            }
            if ((modifiers & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {}
            if ((modifiers & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
                if(state.equals("end")) {
//                    setVisible(false);
//                    g.free = true;
                }
                else {
                    getResult();
                }
            }
        }
    }

   class TimeListener implements ActionListener {
    	 public void actionPerformed(ActionEvent e) {
    		//... Whenever this is called, get the current time and
    		//    display it in the textfield.
            secs--;
            if(secs>=0) {
                int min = secs/60;
                int sec = secs%60;
                lblTime.setText(min+":"+((sec<10)?"0":"")+sec);
            }

            if(secs==0) {
                lblSubmit.setVisible(false);
                lblSelect.setVisible(false);
                lblResult.setText("Sorry, your time is up.");
				writeLog (playerId + ",,\"" + params + "\"," + repNum + ","
					+ repTot + "," + "TimeOut,TimeOut");
                state="end";
                System.out.println("G.totalMoneyWon = " + totalMoneyWon) ;
            }

            if(secs==-6) {
                time.stop();
                try {
                    setVisible(false);
                    free=true;
                } catch(Exception ex) {
                    ex.printStackTrace();
                    logError(ex);
                }
            }
    	}

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        lblResult = new javax.swing.JLabel();
        lblTime = new javax.swing.JLabel();
        lblInst = new javax.swing.JLabel();
        lblSubmit = new javax.swing.JLabel();
        lblSelect = new javax.swing.JLabel();
        moneyScroll = new javax.swing.JScrollPane();
        valueList = new javax.swing.JList();

        setBorder(null);
        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setPreferredSize(new java.awt.Dimension(800, 600));

        jPanel1.setBackground(new java.awt.Color(255, 255, 255));
        jPanel1.setPreferredSize(new java.awt.Dimension(800, 600));

        lblResult.setFont(new java.awt.Font("Calibri", 1, 28));
        lblResult.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

        lblTime.setFont(new java.awt.Font("Calibri", 1, 36));
        lblTime.setForeground(new java.awt.Color(153, 102, 0));
        lblTime.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/hrGlass.png"))); // NOI18N
        lblTime.setText("3:00");

        lblInst.setFont(new java.awt.Font("Calibri", 1, 32));
        lblInst.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lblInst.setText("Select a number ");

        lblSubmit.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/greenSubmit.png"))); // NOI18N

        lblSelect.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/redSelect.png"))); // NOI18N

        valueList.setFont(new java.awt.Font("Tahoma", 1, 24));
        valueList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "1", "2", "3", "4", "5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        valueList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        valueList.setVisibleRowCount(5);
        valueList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                valueListValueChanged(evt);
            }
        });
        moneyScroll.setViewportView(valueList);

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(lblInst, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
                .addContainerGap())
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(lblTime, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
                .addContainerGap())
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap(136, Short.MAX_VALUE)
                .add(lblSelect)
                .add(81, 81, 81)
                .add(lblSubmit)
                .add(117, 117, 117))
            .add(jPanel1Layout.createSequentialGroup()
                .add(226, 226, 226)
                .add(lblResult, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)
                .add(245, 245, 245))
            .add(jPanel1Layout.createSequentialGroup()
                .add(371, 371, 371)
                .add(moneyScroll, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 59, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(370, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(lblTime, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 70, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(18, 18, 18)
                .add(lblInst, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(moneyScroll, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 160, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 22, Short.MAX_VALUE)
                .add(lblResult, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 88, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(18, 18, 18)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(lblSubmit)
                    .add(lblSelect))
                .add(87, 87, 87))
        );

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	/**
	 * Don't let subject change the value of the list.
	 *
	 * @param evt
	 */
	private void valueListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_valueListValueChanged
		valueList.setSelectedIndex(halfList);
}//GEN-LAST:event_valueListValueChanged

    /*Funciton to populate the drop down box for numbers*/
//    void populateList()
//    {
//        for(int i=1; i<this.limit; i++)
//            cmbNumbers.addItem(i);
//    }

    /*Function to run the game logic and display the result*/
/*    void getResult() {
        Random rand = new Random();
        double avg = 28.8;
        avg = avg * factor;
        int range = rand.nextInt(14);
        int selNum = Integer.parseInt(valueList.getSelectedValue().toString());

        timeTaken = totalTime-secs;

        if(selNum > avg-range && selNum < avg+range) {
            lblResult.setText("Ok.");
			writeLog (playerId + ",,\"" + params + "\"," + repNum + ","
				+ repTot + "," + String.format("$%.2f", win_amount) + ",$0.00");
			writeGameLog (playerId + "," + timeTaken + "," + selNum + ","
				+ GL_WIN_WIN + "," + (avg-range) + "-" + (avg+range));
            totalMoneyWon += win_amount ;
            System.out.println("G.totalMoneyWon = " + totalMoneyWon) ;
        }
        else {
            lblResult.setText("Ok.");
			writeLog (playerId + ",,\"" + params + "\"," + repNum + ","
				+ repTot + ",$0.00," + String.format("$%.2f", win_amount));
            writeGameLog (playerId + "," + timeTaken + "," + selNum + ","
				+ GL_WIN_LOSS + "," + (avg-range) + "-" + (avg+range));
            System.out.println("G.totalMoneyWon = " + totalMoneyWon) ;
        }
        lblSubmit.setVisible(false);
        lblSelect.setVisible(false);
        state="end";
        secs=0;
    }*/

    void getResult()
    {
        Random rand = new Random();
        int oppChoice[] = new int[participants];
        int sum=0;
        double avg,diff,min=this.limit;
        for(int i=0; i<this.participants; i++)
        {
            oppChoice[i] = rand.nextInt(limit);
            System.out.println("Generated "+oppChoice[i]);
            sum += oppChoice[i];
        }
        avg = sum/this.participants;
        avg = avg * factor;
		int selNum = Integer.parseInt(valueList.getSelectedValue().toString());
		timeTaken = totalTime-secs;

        for(int i=0; i<participants; i++)
        {
            diff = Math.abs(avg - oppChoice[i]);
            if(diff<min)
                min=diff;
        }

        //System.out.println("Average is "+avg+". Minimum is "+min);
        //String logText = "BeautyContest, params : #ofParticipants="+participants+" factor="+factor+" limit="+limit+" time="+timeTaken+"s, Result : $";
		lblResult.setText("Ok.");
        if(Math.abs(avg - selNum) <= min) // Subject wins.
        {
			totalMoneyWon += win_amount;
            writeLog (playerId + ",,\"" + params + "\"," + repNum + "," +
				repTot + "," +  String.format("$%.2f", win_amount) + ",$0.00");
            writeGameLog (playerId + "," + timeTaken + "," + selNum + ","
				+ GL_WIN_WIN + "," + avg);
        }
        else
        {
            writeLog (playerId + ",,\"" + params + "\"," + repNum + ","
				+ repTot + ",$0.00," + String.format("$%.2f", win_amount));
            writeGameLog (playerId + "," + timeTaken + "," + selNum + ","
				+ GL_WIN_LOSS + "," + avg); 
        }
		// System.out.println("(Beauty-Contest) G.totalMoneyWon = " + totalMoneyWon);
        lblSubmit.setVisible(false);
        lblSelect.setVisible(false);
        secs=0;
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        try {
            JFrame main = new JFrame();
            JDesktopPane dPane = new JDesktopPane();
            BeautyContest frame = new BeautyContest();
            main.setSize(820, 620);
            dPane.add(frame);
            main.add(dPane);
            main.setVisible(true);
            dPane.setVisible(true);
            frame.setSelected(true);
            frame.setVisible(true);
            } catch(Exception ex) {
            ex.printStackTrace();
            }

    }



    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel jPanel1;
    private javax.swing.JLabel lblInst;
    private javax.swing.JLabel lblResult;
    private javax.swing.JLabel lblSelect;
    private javax.swing.JLabel lblSubmit;
    private javax.swing.JLabel lblTime;
    private javax.swing.JScrollPane moneyScroll;
    private javax.swing.JList valueList;
    // End of variables declaration//GEN-END:variables

}
